package com.zmn.mcc.business.impl.menu;

import com.alibaba.fastjson.JSON;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.cube.common.utils.CollectionUtil;
import com.zmn.mcc.business.interfaces.menu.MenuBService;
import com.zmn.mcc.common.constant.MenuConsts;
import com.zmn.mcc.model.entity.menu.McMenu;
import com.zmn.mcc.model.entity.menu.McMenuQuery;
import com.zmn.mcc.services.interfaces.menu.MenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.zmn.mcc.common.constant.MenuConsts.MENU_LEVEL_FIRST_LEVEL;
import static com.zmn.mcc.common.constant.MenuConsts.MENU_LEVEL_STEP_SIZE;

/**
 * 描述: 菜单管理
 *
 * @author jiafei
 * @version 1.0
 * @since 2021/6/11 11:45
 */
@Slf4j
@Service
public class MenuBServiceImpl implements MenuBService {

	private static final String TAG = "菜单配置表基础服务接口";

	@Resource
	private MenuService menuService;


	@Override
	public List<McMenu> treeMenu() {

		McMenuQuery query = new McMenuQuery();
		query.setStatus(GlobalConsts.YES);
		query.setMenuType(MenuConsts.MENU_TYPE_WHOLE_KEY);
		List<McMenu> mcMenus = menuService.listByQuery(query);

		// 根据父级id分组
		Map<Integer, List<McMenu>> mcMenuMap = mcMenus.stream().collect(Collectors.groupingBy(McMenu::getParentId));

		// 构建tree
		return buildTreeMenu(mcMenuMap.get(MenuConsts.MENU_FIRST_LEVEL_PARENT_ID), mcMenuMap, null);
	}

	/**
	 * 描述: 构建树形菜单列表
	 *
	 * @param menus     menus
	 * @param mcMenuMap 根据父级id分组菜单
	 * @param result    返回结果
	 * @return java.util.List<com.zmn.mcc.model.entity.menu.McMenu>
	 * @author jiafei
	 * @since 2021/7/14 15:19
	 */
	private List<McMenu> buildTreeMenu(List<McMenu> menus, Map<Integer, List<McMenu>> mcMenuMap,
									   List<McMenu> result) {

		// menus 排序 根据sort排序
		menus = menus.stream()
					 .sorted(Comparator.comparing(menu -> Objects.isNull(menu.getSort()) ? 0 : menu.getSort()))
					 .collect(Collectors.toList());

		// 初始化返回结果
		if (Objects.isNull(result)) {
			result = new ArrayList<>();
		}

		List<McMenu> treeMenus = result;
		menus.forEach(item -> {

			treeMenus.add(setShowTreeMenuName(item));

			// 获取子级菜单
			List<McMenu> subMenus = mcMenuMap.get(item.getMenuId());

			// 没有子级菜单结束
			if (Objects.isNull(subMenus)) {
				return;
			}
			buildTreeMenu(subMenus, mcMenuMap, treeMenus);
		});
		return treeMenus;
	}

	/**
	 * 描述: 设置菜单名称前缀
	 * 例如: 	一级菜单1
	 * --二级菜单
	 * ----三级菜单
	 * --一级菜单2
	 * ----二级菜单2
	 *
	 * @param mcMenu mcMenu
	 * @author jiafei
	 * @since 2021/7/14 15:17
	 */
	private McMenu setShowTreeMenuName(McMenu mcMenu) {

		if (Objects.equals(mcMenu.getParentId(), MenuConsts.MENU_FIRST_LEVEL_PARENT_ID)) {
			return mcMenu;
		}
		String str = "---";
		Supplier<String> supplier = str::toString;
		String prefix = Stream.generate(supplier).limit(mcMenu.getMenuLevel() - 1).collect(Collectors.joining());
		mcMenu.setMenuName(prefix + mcMenu.getMenuName());
		return mcMenu;
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public List<String> updateStatusBatch(List<Integer> ids, Integer status, String operator) {

		List<String> resultMsg = new ArrayList<>();
		if (!Objects.equals(status, GlobalConsts.NO) && !Objects.equals(status, GlobalConsts.YES)) {
			log.error("[{}],status状态超出取值范围", TAG);
			return resultMsg;
		}

		// 启用是判断父级是否启用
		if (Objects.equals(MenuConsts.STATUS_START_KEY, status)) {

			// 排序 启用修改 id从小到大 修改
			ids = ids.stream().sorted().collect(Collectors.toList());
			ids.forEach(id -> {
				McMenu mcMenu = menuService.findById(id);
				if (mcMenu == null) {
					return;
				}
				//顶级或者父级状态为开启直接开启
				McMenu parentMenu = menuService.findById(mcMenu.getParentId());
				if (Objects.equals(mcMenu.getParentId(), MenuConsts.MENU_FIRST_LEVEL_PARENT_ID) ||
					Objects.equals(parentMenu.getStatus(), MenuConsts.STATUS_START_KEY)) {
					mcMenu.setStatus(MenuConsts.STATUS_START_KEY);
					mcMenu.setUpdater(operator);
					mcMenu.setUpdateTime(DateUtil.getNow());
					menuService.updateByKey(mcMenu);
				} else {
					resultMsg.add(mcMenu.getMenuName());
					log.info("启用id的父级状态为停用: mcMenu={}", mcMenu);
				}
			});

		} else { //关闭
			// 倒序 关闭id从大到小修改
			ids = ids.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
			ids.forEach(id -> {
				McMenu mcMenu = menuService.findById(id);
				if (mcMenu == null) {
					return;
				}
				// 底层菜单 或者下级目录已关闭的
				List<McMenu> subMenus = menuService.findByParentIdAndStatus(mcMenu.getMenuId(),
																			MenuConsts.STATUS_START_KEY);
				if (Objects.equals(mcMenu.getMenuType(), MenuConsts.MENU_TYPE_MENU_KEY) ||
					CollectionUtil.isNullOrEmpty(subMenus)) {
					mcMenu.setStatus(MenuConsts.STATUS_STOP_KEY);
					mcMenu.setUpdater(operator);
					mcMenu.setUpdateTime(DateUtil.getNow());
					menuService.updateByKey(mcMenu);
				} else {
					resultMsg.add(mcMenu.getMenuName());
					log.info("关闭id的子级状态为启用: mcMenu={}", JSON.toJSONString(subMenus));
				}
			});
		}
		return resultMsg;
	}


    @Override
    public Integer insert(McMenu mcMenu) {

        if (Objects.isNull(mcMenu)) {
            log.error("[{}],新增数据,McMenu为null", TAG);
            return null;
        }
        // 计算菜单等级
        McMenu parentMenu = menuService.findById(mcMenu.getParentId());
        int menuLevel = MENU_LEVEL_FIRST_LEVEL;
        // 不是根目录
        if (Objects.nonNull(parentMenu) && Objects.nonNull(parentMenu.getParentId())) {
            menuLevel = Math.addExact(parentMenu.getMenuLevel(), MENU_LEVEL_STEP_SIZE);
        }
        mcMenu.setMenuLevel(menuLevel);

        //如果是一级目录 添加parentId
        if (Objects.equals(mcMenu.getMenuLevel(), MenuConsts.MENU_FIRST_LEVEL_PARENT_ID)) {
            mcMenu.setParentId(MenuConsts.MENU_FIRST_LEVEL_PARENT_ID);
        }

        return menuService.insert(mcMenu);
    }
}
